import React, { useState, useRef, useEffect } from 'react';
import sdk, { blueToothAdapter, StandardDeviceAdapter, ERROR_MESSAGES } from 'qcloud-iotexplorer-h5-panel-sdk';
import { str2bin } from './str2bin';

const REPORT_EVENT_TYPE = 'STANDARD_BLE';

export const StandardBleConnectStatus = {
  DISCONNECTED: 'disconnected',
  CONNECTING: 'connecting',
  CONNECTED: 'connected',
  ERROR: 'connect-error',
};

export const StandardBleConnectStatusStr = {
  [StandardBleConnectStatus.DISCONNECTED]: '蓝牙未连接',
  [StandardBleConnectStatus.CONNECTING]: '蓝牙连接中',
  [StandardBleConnectStatus.CONNECTED]: '蓝牙已连接',
  [StandardBleConnectStatus.ERROR]: '无法连接蓝牙设备',
};
// 获取连接状态
export const getStandardBleConnectStatusInfo = (connectStatus = StandardBleConnectStatus.DISCONNECTED, msg) => {
  if (!StandardBleConnectStatusStr[connectStatus]) {
    connectStatus = StandardBleConnectStatus.DISCONNECTED;
  }

  return {
    status: connectStatus,
    msg: msg || StandardBleConnectStatusStr[connectStatus],
  };
};

export const useStandardBleConnector = ({
  deviceId,
  familyId = '',
}) => {
  const { deviceInfo, productInfo } = sdk;
  // 跨生命周期存储蓝牙适配器实例
  const deviceAdapterRef = useRef(null);
  const [connectStatusInfo, setConnectStatusInfo] = useState(getStandardBleConnectStatusInfo());
  const [isconnected, setisconnected] = useState(false)
  const [bleMessage, setblemessage] = useState({})
  const [bleData, setbleData] = useState({})
  // 获取设备适配器实例
  const getDeviceAdapter = () => {
    let deviceAdapter = deviceAdapterRef.current;

    if (!deviceAdapter) {
      deviceAdapter = blueToothAdapter.getDeviceAdapter({
        explorerDeviceId: deviceId,
      });
    }

    return deviceAdapter;
  };
  // 蓝牙连接状态
  const isDeviceReady = (deviceAdapter) => {
    deviceAdapter = deviceAdapter || deviceAdapterRef.current;
    return deviceAdapter && deviceAdapter.isConnected && deviceAdapter.authorized;
  };

  const updateDeviceConnectStatusInfo = (connectStatus, msg = '') => {
    // 储存XXX状态
    setConnectStatusInfo(getStandardBleConnectStatusInfo(connectStatus, msg));
  };

  // 连接状态的双向数据更新
  const onAuthorizedRef = useRef(() => {
    // 需要蓝牙连接认证通过才行
    console.log('---on---authorized---');
    updateDeviceConnectStatusInfo(StandardBleConnectStatus.CONNECTED);
    setisconnected(true)
  });

  const onDisconnectRef = useRef(() => {
    console.log('---on---disconnect---');
    updateDeviceConnectStatusInfo(StandardBleConnectStatus.DISCONNECTED);
    setisconnected(false)
  });
  const onConnectRef = useRef(() => {
    console.log('---on---connect---');
    updateDeviceConnectStatusInfo(StandardBleConnectStatus.CONNECTED);
    setisconnected(true)
  });
  // 检查蓝牙是否连接
  const checkDeviceAdapter = async () => {
    try {
      const deviceReady = isDeviceReady();

      if (!deviceReady) {
        await sdk.tips.showInfo('请先连接至蓝牙设备');
        return false;
      }
      return true;
    } catch (e) {
      console.error(e);
      return false;
    }
  };
  // 控制设备
  const controlDevice = async ( deviceData ) => {
    if (!await checkDeviceAdapter()) return;
    console.log(deviceData)
    await deviceAdapterRef.current.controlDevice({ deviceData });
  };
  // 控制动作
  const controlAction = async ({ actionData }) => {
    if (!await checkDeviceAdapter()) return;
    await deviceAdapterRef.current.controlAction({ actionData });
  };
  // 连接设备
  const connectDevice = async () => {
    try {
      console.log('connect device');
      const [productId, deviceName] = deviceId.split('/');

      let deviceAdapter = getDeviceAdapter();

      if (!isDeviceReady(deviceAdapter)) {
        console.log('device not ready');

        updateDeviceConnectStatusInfo(StandardBleConnectStatus.CONNECTING);

        if (!deviceAdapter) {
          console.log('no adapter');

          await blueToothAdapter.init();

          const device = await blueToothAdapter.searchDevice({
            serviceId: StandardDeviceAdapter.serviceId,
            productId,
            deviceName,
            // 因为要使用广播中的version来判断发包，所以不使用缓存吧
            disableCache: true,
          });

          console.log('searchDevice result', device);

          if (device) {
            deviceAdapter = await blueToothAdapter.connectDevice(device);
          }
        }

        // 如果还是没有的话
        if (!deviceAdapter) {
          throw {
            code: 'CANNOT_FIND_DEVICE',
          };
        }

        if (!deviceAdapter.isConnected) {
          await deviceAdapter.connectDevice();
        }

        if (!deviceAdapter.authorized) {
          // 走再次连接的流程
          await deviceAdapter.authenticateConnection({
            deviceName,
          });
        }
      }
      deviceAdapterRef.current = deviceAdapter;
      // 取消监听设备适配器事件。
      deviceAdapter.off('connect', onConnectRef.current);
      deviceAdapter.off('message', onMessageRef.current);
      deviceAdapter.off('disconnect', onDisconnectRef.current);
      deviceAdapter.off('authorized', onAuthorizedRef.current);
      // 监听设备适配器事件
      deviceAdapter.on('connect', onConnectRef.current);
      deviceAdapter.on('message', onMessageRef.current);
      deviceAdapter.on('disconnect', onDisconnectRef.current);
      deviceAdapter.on('authorized', onAuthorizedRef.current);

      updateDeviceConnectStatusInfo(StandardBleConnectStatus.CONNECTED);
    } catch (err) {
      console.error(err);
      if (err) {
        updateDeviceConnectStatusInfo(StandardBleConnectStatus.ERROR, err.errCode || err.msg ? err.msg : '');

        sdk.insightReportor.error(REPORT_EVENT_TYPE, {
          message: ERROR_MESSAGES[err.code] || ERROR_MESSAGES.CONNECT_DEVICE_ERROR,
          error: err,
          data: {
            error: err,
          },
        });
      }
    }
  };
  // 删除设备
  const deleteDevice = async () => {
    if (!isDeviceReady()) {
      const isConfirm = confirm('确定要删除这个设备吗？当前设备未连接,删除后如需重新绑定需要初始化蓝牙设备。');

      if (!isConfirm) {
        return Promise.reject();
      } else {
        return sdk.requestTokenApi('AppDeleteDeviceInFamily', {
          FamilyId: familyId,
          DeviceId: deviceId,
        });
      }
    }

    if (!familyId) return Promise.reject('无家庭信息，无法删除');

    try {
      // @ts-ignore
      await deviceAdapterRef.current.unbindDevice({
        familyId,
        deviceName: deviceInfo.DeviceName,
      });
      return true;
    } catch (error) {
      return Promise.reject(error);
    }
  };
  // 断开连接设备
  const disconnectDevice = async () => {
    if (!deviceAdapterRef.current) return;

    await deviceAdapterRef.current.disconnectDevice();
  };
  // 蓝牙广播存储
  const onMessageRef = useRef(message => {
    var isend = false;
    if(message.type == "unknown"){
      const jxdata = jxBleData(message.data);
      console.log("message消息类型",message.type)
      console.log("message内容时间：",new Date(message.timestamp).toLocaleString())
      console.log("message内容：",jxdata)
      let msd = ""
      message.data.map((val,idx)=>{
        msd = val
      })
      let tempMsgData = message.data.join("")
      console.log("tempMsgData内容1：",tempMsgData)
      const addZero1 = (num, len = 2) => (`0${num}`).slice(-len)
      const addZero2 = (num, len = 2) => (`${num}`).padStart(len , '0')
      console.log(chk8xor(str2Arr('01A07CFF02',2)));
      switch(jxdata.weight_unit){
        case 1:
          let temp = (parseFloat((jxdata.weight*0.5).toFixed(2)))*100
          console.log("tempMsgData内容2：",temp,addZero2(temp.toString(16),4))
          tempMsgData = (addZero2(temp.toString(16),4) + tempMsgData.substring(4)).toUpperCase()
          // tempMsgData = temp+message.data.slice(1,3)
          break
      }
      console.log("tempMsgData内容4：",tempMsgData)
      setbleData(tempMsgData)
      setblemessage(jxdata)
    }
	});
  const jxBleData = (res:string []) =>{
    let tempJx = {
      weight:0,body_r:0,weight_unit:0,stable_data_flag:0
    }
    // 消息体属性
    // bit7	bit6	bit5	bit4	bit3	bit2	bit1	bit0
    // 保留			          单位选择		 小数点		数据类型
    // 单位选择(bit4-bit3)
    // 00 = 公斤 0
    // 01 = 斤 3
    // 10 = 磅 1
    // 小数点位数选择(bit2-bit1)
    // 00 = 1位小数点
    // 01 = 0位小数点
    // 10 = 2位小数点
    // 数据类型(bit0)
    // 0 = 非锁定数据
    // 1 = 锁定数据
    let scArry = (str:String) =>{
      console.log("scstr：",str)
      let sc = 0
      switch(str){
        case "00":
          sc = 0.1
          break;
        case "01": 
          sc = 1
          break;
        case "10":
          sc = 0.01
          break;
      }
      console.log("sc：",sc)
      return sc
    }
    let unitArry = (str:String) =>{
      console.log("单位str",str)
      let unit = 0
      switch(str){
        case "00":
          unit = 0 
          break;
        case "01":
          unit = 1  
          break;
        case "10":
          unit = 2
          break;
      }
      console.log("计算后单位：",unit)
      return unit
    }
    let jqweight = (unit:number,str:number) =>{
      console.log("jqweight",str)
      let weight = ""
      switch(unit){
        case 0:
          weight = str.toFixed(2) 
          break;
        case 1:
          weight = str.toFixed(1)  
          break;
        case 2:
          weight = str.toFixed(1)
          break;
      }
      console.log("计算后weight：",weight)
      return weight
    }
    // let msgS = strToBinary(res[4])
    // console.log("要解析的数据：",res)
    // tempJx["weight"] = (parseInt(res[0]+res[1], 16))*0.01
    // tempJx["weight_unit"] = unitArry(msgS.slice(3,5))
    // tempJx["stable_data_flag"] = parseInt(msgS.slice(0,1))
    
    let tempmsgS = str2bin(res[4],false)
    // let msgS = (tempmsgS[0].substr(4)+tempmsgS[1].substr(4)).split("").reverse().join("")
    let msgS = (tempmsgS[0].substr(4)+tempmsgS[1].substr(4)).split("").reverse()
    // let sc = scArry(msgS.slice(1,3))
    let sc = scArry(msgS[2]+msgS[1])
    console.log("要解析的数据：",res)
    console.log("消息体：",msgS)
    tempJx["weight"] = parseFloat(jqweight(unitArry(msgS[4]+msgS[3]),((parseInt(res[0]+res[1], 16))*sc)))
    tempJx["body_r"] = (parseInt(res[2]+res[3], 16))
    // tempJx["weight_unit"] = unitArry(msgS.slice(3,5))
    tempJx["weight_unit"] = unitArry(msgS[4]+msgS[3])
    tempJx["stable_data_flag"] = parseInt(msgS[0])
    console.log("解析后的数据：",tempJx)
    return tempJx
  }
  const stringtoHex = (str:String) =>{
    var val = "";
    for (var i = 0; i < str.length; i++) {
      if (val == "")
        val = str.charCodeAt(i).toString(16);
      else
        val += str.charCodeAt(i).toString(16);
    }
    val += "0a"
    return val
  }
  const strToBinary = (str:String) =>{
    console.log("strToBinary消息体源数据",str)
    var result = [];
    var list = str.split("");
    list.map((item,idx)=>{
      console.log(idx)
      console.log(item)
      var binaryStr = item.charCodeAt(0).toString(2);
      console.log(binaryStr)
      result.push(binaryStr.slice(3,7))
    })
    console.log(result)
    return result.join("");
  }
  useEffect(() => {
    console.log('in effect', { deviceId, connectStatusInfo });
    if (deviceId) {
      connectDevice();
      return () => {
        if (deviceAdapterRef.current) {
          deviceAdapterRef.current.off('connect', onConnectRef.current);
          deviceAdapterRef.current.off('message', onMessageRef.current);
          deviceAdapterRef.current.off('disconnect', onDisconnectRef.current);
          deviceAdapterRef.current.off('authorized', onAuthorizedRef.current);
          // 销毁这个实例
          deviceAdapterRef.current = null;
        }
      };
    }
  }, [deviceId]);
  return [
    connectStatusInfo,
    isconnected, //蓝牙连接状态
    bleMessage, //蓝牙广播
    bleData,
    {
      deviceAdapter: deviceAdapterRef.current, //蓝牙适配器实例
      connectDevice,//连接设备
      deleteDevice,//删除设备
      controlDevice,//控制设备
      disconnectDevice,//断开连接设备
      controlAction,//控制动作
    },
  ];
};

//异或校验
function chk8xor(hexarr:Array<string>) {
  var bcc = 0;
  var xor = 0;
  for(var i= 0; i< hexarr.length; i++){
    var hexint = parseInt(hexarr[i],16);
    if(i==0){ xor = hexint; }
    else {
      bcc = xor ^ hexint;
      xor = bcc;
    }
  }
  return fillZero(bcc.toString(16),2)
}
//字符串长度判断不足填充0
function fillZero(num:string, n:number) {
  var len = num.toString().length;
  while(len < n) {
    num = "0" + num;
    len++;
  }
  return num;
}
//字符串转为数组
function str2Arr(str:string,num:number){
  var arr = [];
  var len = str.length;
  for (let index = 0; index < len; index+=num) {
    arr.push(str.slice(index,index+num));
  }
  return arr;
}